package com.ssy.lingxi.order.serviceimpl.feign;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.group.GroupBy;
import com.querydsl.core.types.Projections;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.ssy.lingxi.common.constant.basic.FundModeEnum;
import com.ssy.lingxi.common.constant.marketing.BelongTypeEnum;
import com.ssy.lingxi.common.constant.order.OrderPayChannelEnum;
import com.ssy.lingxi.common.constant.order.OrderPayTypeEnum;
import com.ssy.lingxi.common.constant.order.OrderPaymentParameterEnum;
import com.ssy.lingxi.common.constant.order.OrderTypeEnum;
import com.ssy.lingxi.common.exception.BusinessException;
import com.ssy.lingxi.common.model.dto.MemberAndRoleIdDTO;
import com.ssy.lingxi.common.response.PageData;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.common.utils.DateUtil;
import com.ssy.lingxi.contract.api.model.vo.response.ContractPriceQueryVO;
import com.ssy.lingxi.order.api.model.vo.request.*;
import com.ssy.lingxi.order.api.model.vo.response.*;
import com.ssy.lingxi.order.entity.*;
import com.ssy.lingxi.order.model.bo.*;
import com.ssy.lingxi.order.model.constant.BuyerInnerStatusEnum;
import com.ssy.lingxi.order.model.constant.OrderOuterStatusEnum;
import com.ssy.lingxi.order.model.constant.OrderServiceContants;
import com.ssy.lingxi.order.model.dto.OrderReturnAmountDTO;
import com.ssy.lingxi.order.repository.OrderProductRepository;
import com.ssy.lingxi.order.repository.OrderRepository;
import com.ssy.lingxi.order.service.base.IBaseOrderPaymentService;
import com.ssy.lingxi.order.service.base.IBaseOrderProcessService;
import com.ssy.lingxi.order.service.feign.IOrderFeignService;
import com.ssy.lingxi.order.service.platform.IPlatformSettlementTypeService;
import com.ssy.lingxi.order.service.web.IBuyerOrderService;
import com.ssy.lingxi.order.service.web.IOrderParamConfigService;
import com.ssy.lingxi.order.utils.NumberUtil;
import com.ssy.lingxi.order.utils.OrderStringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 订单服务对外OpenFeign接口实现类
 * @author 万宁
 * @version 2.0.0
 * @date 2021-07-31
 */
@Service
public class OrderFeignServiceImpl implements IOrderFeignService {
    private static final Logger logger = LoggerFactory.getLogger(OrderFeignServiceImpl.class);

    @Resource
    private IBaseOrderProcessService baseOrderProcessService;

    @Resource
    private OrderProductRepository orderProductRepository;

    @Resource
    private IBaseOrderPaymentService baseOrderPaymentService;

    @Resource
    private IBuyerOrderService buyerOrderService;

    @Resource
    private IPlatformSettlementTypeService platformSettlementTypeService;

    @Resource
    private OrderRepository orderRepository;

    @Resource
    private JPAQueryFactory jpaQueryFactory;
    @Resource
    private IOrderParamConfigService orderParamConfigService;

    /**
     * 查询（供应）会员交易流程规则配置
     *
     * @param feignVO 接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<OrderTradeProcessFeignDetailVO> findVendorTradeProcess(OrderTradeProcessFeignVO feignVO) {
        VendorProductBO vendorProduct = new VendorProductBO();
        vendorProduct.setVendorMemberId(feignVO.getMemberId());
        vendorProduct.setVendorRoleId(feignVO.getRoleId());
        vendorProduct.setProducts(CollectionUtils.isEmpty(feignVO.getProducts()) ? new ArrayList<>() : feignVO.getProducts().stream().map(p -> new OrderProductBO(p.getProductId(), p.getSkuId())).collect(Collectors.toList()));

        Wrapper<OrderTradeProcessBO> result = baseOrderProcessService.findVendorTradeProcess(feignVO.getShopId(), feignVO.getProcessTypeEnum(), Collections.singletonList(vendorProduct));
        if(result.getCode() != ResponseCode.SUCCESS.getCode()) {
            return Wrapper.fail(result.getCode(), result.getMessage());
        }

        OrderTradeProcessFeignDetailVO detailVO = new OrderTradeProcessFeignDetailVO();
        detailVO.setProcessKey(result.getData().getProcessKey());
        detailVO.setSkipFirstStep(result.getData().getSkipFirstStep());
        detailVO.setProcessKind(result.getData().getProcessKind());
        detailVO.setExpireHours(result.getData().getExpireHours());
        detailVO.setPayTimes(result.getData().getPayTimes());
        detailVO.setPayments(result.getData().getPayNodes().stream().map(processPayment -> new OrderTradeProcessPaymentFeignDetailVO(processPayment.getBatchNo(), processPayment.getPayNode(), processPayment.getPayRate())).collect(Collectors.toList()));
        return Wrapper.success(detailVO);
    }

    /**
     * 查询（采购）会员采购流程规则配置
     *
     * @param feignVO 接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<OrderPurchaseProcessFeignDetailVO> findBuyerPurchaseProcess(OrderPurchaseProcessFeignVO feignVO) {
        List<Long> contractIds = CollectionUtils.isEmpty(feignVO.getContractIds()) ? new ArrayList<>() : feignVO.getContractIds().stream().distinct().collect(Collectors.toList());
        Wrapper<OrderPurchaseProcessBO> result = baseOrderProcessService.findBuyerPurchaseProcess(feignVO.getMemberId(), feignVO.getRoleId(), feignVO.getProcessTypeEnum(), contractIds);
        if(result.getCode() != ResponseCode.SUCCESS.getCode()) {
            return Wrapper.fail(result.getCode(), result.getMessage());
        }

        OrderPurchaseProcessFeignDetailVO detailVO = new OrderPurchaseProcessFeignDetailVO();
        detailVO.setProcessKey(result.getData().getProcessKey());
        detailVO.setProcessKind(result.getData().getProcessKind());
        detailVO.setSkipFirstStep(result.getData().getSkipFirstStep());
        return Wrapper.success(detailVO);
    }

    /**
     * 查询平台后台 - 会员支付策略设置
     *
     * @param feignVO 接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<List<PlatformPayTypeFeignDetailVO>> findPlatformPayments(OrderMemberFeignVO feignVO) {
        List<PlatformPayTypeBO> platformPayTypes = baseOrderProcessService.findPlatformMemberPayment(feignVO.getMemberId(), feignVO.getRoleId());
        if(feignVO.getPayType() != null) {
            platformPayTypes = platformPayTypes.stream().filter(platformPayType -> platformPayType.getPayType().equals(feignVO.getPayType().getCode())).collect(Collectors.toList());
        }

        if(feignVO.getPayChannel() != null) {
            platformPayTypes = platformPayTypes.stream().filter(platformPayType -> platformPayType.getChannels().stream().anyMatch(payChannel -> payChannel.getPayChannel().equals(feignVO.getPayChannel().getCode()))).collect(Collectors.toList());
        }

        if(CollectionUtils.isEmpty(platformPayTypes)) {
            return Wrapper.fail(ResponseCode.ORDER_PAYMENT_SETTING_NOT_SET_YET);
        }

        return Wrapper.success(platformPayTypes.stream().map(platformPayType -> {
            PlatformPayTypeFeignDetailVO detailVO = new PlatformPayTypeFeignDetailVO();
            detailVO.setFundMode(FundModeEnum.parse(platformPayType.getFundMode()));
            detailVO.setPayType(OrderPayTypeEnum.parse(platformPayType.getPayType()));
            detailVO.setPayChannels(platformPayType.getChannels().stream().map(channel -> OrderPayChannelEnum.parse(channel.getPayChannel())).collect(Collectors.toList()));
            return detailVO;
        }).collect(Collectors.toList()));
    }

    /**
     * 查询支付参数
     *
     * @param feignVO 接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<PaymentParameterFeignDetailVO> findPaymentParameters(OrderPayParameterFeignVO feignVO) {
        Wrapper<OrderPaymentParameterDetailBO> parameterResult = baseOrderProcessService.findOrderPaymentParameters(feignVO.getPayChannel().getCode(), feignVO.getMemberId(), feignVO.getRoleId());
        if(parameterResult.getCode() != ResponseCode.SUCCESS.getCode()) {
            return Wrapper.fail(parameterResult.getCode(), parameterResult.getMessage());
        }

        return Wrapper.success(new PaymentParameterFeignDetailVO(parameterResult.getData().getMemberId(), parameterResult.getData().getRoleId(), FundModeEnum.parse(parameterResult.getData().getFundMode()), OrderPayChannelEnum.parse(parameterResult.getData().getPayChannel()), parameterResult.getData().getParameters().stream().map(p -> new PayChannelParameterFeignDetailVO(OrderPaymentParameterEnum.parse(p.getCode()), p.getValue())).collect(Collectors.toList())));
    }

    /**
     * 查询支付参数（直接查询平台支付参数配置）
     *
     * @param feignVO 接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<PaymentParameterFeignDetailVO> findPlatformPaymentParameters(OrderPayChannelFeignVO feignVO) {
        Wrapper<OrderPaymentParameterDetailBO> parameterResult = baseOrderProcessService.findPlatformPaymentParameters(feignVO.getPayChannel().getCode());
        if(parameterResult.getCode() != ResponseCode.SUCCESS.getCode()) {
            return Wrapper.fail(parameterResult.getCode(), parameterResult.getMessage());
        }

        return Wrapper.success(new PaymentParameterFeignDetailVO(parameterResult.getData().getMemberId(), parameterResult.getData().getRoleId(), FundModeEnum.parse(parameterResult.getData().getFundMode()), OrderPayChannelEnum.parse(parameterResult.getData().getPayChannel()), parameterResult.getData().getParameters().stream().map(p -> new PayChannelParameterFeignDetailVO(OrderPaymentParameterEnum.parse(p.getCode()), p.getValue())).collect(Collectors.toList())));
    }

    /**
     * 查询支付参数（直接查询会员支付参数配置）
     *
     * @param feignVO 接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<PaymentParameterFeignDetailVO> findMemberPaymentParameters(OrderPayParameterFeignVO feignVO) {
        Wrapper<OrderPaymentParameterDetailBO> parameterResult = baseOrderProcessService.findMemberPaymentParameters(feignVO.getPayChannel().getCode(), feignVO.getMemberId(), feignVO.getRoleId());
        if(parameterResult.getCode() != ResponseCode.SUCCESS.getCode()) {
            return Wrapper.fail(parameterResult.getCode(), parameterResult.getMessage());
        }

        return Wrapper.success(new PaymentParameterFeignDetailVO(parameterResult.getData().getMemberId(), parameterResult.getData().getRoleId(), FundModeEnum.parse(parameterResult.getData().getFundMode()), OrderPayChannelEnum.parse(parameterResult.getData().getPayChannel()), parameterResult.getData().getParameters().stream().map(p -> new PayChannelParameterFeignDetailVO(OrderPaymentParameterEnum.parse(p.getCode()), p.getValue())).collect(Collectors.toList())));
    }

    /**
     * 售后服务 - 更新订单商品的换货、退货、维修数量
     *
     * @param afterSales 接口参数
     * @return 更新结果
     */
    @Transactional(rollbackFor = BusinessException.class)
    @Override
    public Wrapper<Void> updateAfterSaleOrderProduct(List<OrderAfterSaleVO> afterSales) {
        if(CollectionUtils.isEmpty(afterSales)) {
            return Wrapper.success();
        }

        List<OrderDO> orders = orderRepository.findAllById(afterSales.stream().map(OrderAfterSaleVO::getOrderId).collect(Collectors.toList()));
        if(CollectionUtils.isEmpty(orders) || orders.size() != afterSales.size()) {
            return Wrapper.fail(ResponseCode.ORDER_DOES_NOT_EXIST);
        }

        List<OrderProductDO> orderProducts = orderProductRepository.findByOrderIn(orders);
        if(CollectionUtils.isEmpty(orderProducts)) {
            return Wrapper.fail(ResponseCode.ORDER_PRODUCT_DOES_NOT_EXIST);
        }

        List<OrderProductAfterSaleVO> afterSaleProducts = afterSales.stream().flatMap(a -> a.getProducts().stream()).collect(Collectors.toList());
        orderProducts.forEach(orderProduct -> afterSaleProducts.stream().filter(afterSaleProduct -> afterSaleProduct.getProductId().equals(orderProduct.getId())).findFirst().ifPresent(afterSaleProduct -> {
            orderProduct.setReturnCount(orderProduct.getReturnCount().add(afterSaleProduct.getReturnCount()));
            orderProduct.setExchangeCount(orderProduct.getExchangeCount().add(afterSaleProduct.getExchangeCount()));
            orderProduct.setMaintainCount(orderProduct.getMaintainCount().add(afterSaleProduct.getMaintainCount()));
            orderProduct.setReturnAmount(orderProduct.getReturnAmount().add(afterSaleProduct.getReturnAmount()));
        }));

        orderProductRepository.saveAll(orderProducts);

        return baseOrderPaymentService.batchUpdateOrderPayments(orders, orderProducts.stream().collect(Collectors.groupingBy(p -> p.getOrder().getId())).entrySet().stream().map(entry ->
                new OrderReturnAmountDTO(entry.getKey(), entry.getValue().stream().map(p -> p.getQuantity().subtract(p.getReturnCount()).multiply(p.getRefPrice())).reduce(BigDecimal.ZERO, BigDecimal::add))
        ).collect(Collectors.toList()));
    }

    /**
     * 售后服务 - 更新订单商品的实际退款金额
     *
     * @param orderReturnAmountUpdateVO 退款金额
     * @return 无返回值
     */
    @Override
    public Wrapper<Void> updateAfterSaleOrderProductAmount(OrderReturnAmountUpdateVO orderReturnAmountUpdateVO) {
        if(ObjectUtils.isEmpty(orderReturnAmountUpdateVO)) {
            return Wrapper.success();
        }
        OrderDO order = orderRepository.findById(orderReturnAmountUpdateVO.getOrderId()).orElse(null);
        if(ObjectUtils.isEmpty(order)) {
            return Wrapper.fail(ResponseCode.ORDER_DOES_NOT_EXIST);
        }
        Set<OrderProductDO> products = order.getProducts();
        if(CollectionUtils.isEmpty(products)) {
            return Wrapper.fail(ResponseCode.ORDER_PRODUCT_DOES_NOT_EXIST);
        }
        OrderProductDO orderProductDO = products.stream().filter(p -> p.getId().equals(orderReturnAmountUpdateVO.getProductId()) && p.getSkuId().equals(orderReturnAmountUpdateVO.getSkuId())).distinct().findFirst().orElse(null);
       if(!ObjectUtils.isEmpty(orderProductDO)){
           if(ObjectUtils.isEmpty(orderProductDO.getRefReturnAmount())){
               orderProductDO.setRefReturnAmount(new BigDecimal(0).add(BigDecimal.valueOf(orderReturnAmountUpdateVO.getRefundAmount())));
           }else {
               orderProductDO.setRefReturnAmount(BigDecimal.valueOf(orderReturnAmountUpdateVO.getRefundAmount()).add(orderProductDO.getRefReturnAmount()));
           }

       }
        assert orderProductDO != null;
        orderProductRepository.saveAndFlush(orderProductDO);

        return null ;
    }

    /**
     * 售后服务 - 查询订单商品的换货、退货、维修数量、退款金额
     *
     * @param orderProductIds 订单商品Id列表
     * @return 查询结果
     */
    @Override
    public Wrapper<List<OrderAfterSaleProductFeignDetailVO>> findAfterSaleOrderProducts(List<OrderProductIdFeignVO> orderProductIds) {
        if(CollectionUtils.isEmpty(orderProductIds)) {
            return Wrapper.success();
        }

        List<Long> productIds = orderProductIds.stream().map(OrderProductIdFeignVO::getOrderProductId).collect(Collectors.toList());
        List<OrderProductDO> orderProducts = orderProductRepository.findAllById(productIds);
        if(CollectionUtils.isEmpty(orderProducts)) {
            return Wrapper.fail(ResponseCode.ORDER_PRODUCT_DOES_NOT_EXIST);
        }

        return Wrapper.success(orderProducts.stream().map(orderProduct -> {
            OrderAfterSaleProductFeignDetailVO detailVO = new OrderAfterSaleProductFeignDetailVO();
            detailVO.setOrderProductId(orderProduct.getId());
            detailVO.setQuantity(orderProduct.getQuantity());
            detailVO.setRefPrice(orderProduct.getRefPrice());
            detailVO.setPaidAmount(orderProduct.getPaidAmount());
            detailVO.setExchangeCount(orderProduct.getExchangeCount());
            detailVO.setMaintainCount(orderProduct.getMaintainCount());
            detailVO.setReturnCount(orderProduct.getReturnCount());
            detailVO.setReturnAmount(orderProduct.getReturnAmount());
            return detailVO;
        }).collect(Collectors.toList()));
    }

    /**
     * 售后服务 - 批量查询订单外部状态
     *
     * @param feignVO 订单Id列表
     * @return 查询结果
     */
    @Override
    public Wrapper<List<OrderAfterSaleStatusVO>> findAfterSaleOrderStatuses(OrderIdsFeignVO feignVO) {
        List<OrderDO> orders = CollectionUtils.isEmpty(feignVO.getOrderIds()) ? orderRepository.findByOrderNoIn(feignVO.getOrderNos()) : orderRepository.findAllById(feignVO.getOrderIds());
        return Wrapper.success(orders.stream().map(order -> {
            OrderAfterSaleStatusVO statusVO = new OrderAfterSaleStatusVO();
            statusVO.setOrderId(order.getId());
            statusVO.setOrderNo(order.getOrderNo());
            statusVO.setOuterStatus(order.getOuterStatus());
            statusVO.setOuterStatusName(OrderOuterStatusEnum.getNameByCode(order.getOuterStatus()));
            return statusVO;
        }).collect(Collectors.toList()));
    }

    /**
     * 售后服务 - 根据合同Id查询订单列表
     *
     * @param feignVO 接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<List<OrderAfterSaleOrderContractFeignVO>> findAfterSaleOrderContracts(OrderContractFeignVO feignVO) {
        QOrderDO qOrder = QOrderDO.orderDO;
        QOrderProductDO qOrderProduct = QOrderProductDO.orderProductDO;
        QOrderContractDO qOrderContract = QOrderContractDO.orderContractDO;

        JPAQuery<?> query = jpaQueryFactory.from(qOrderContract)
                .leftJoin(qOrder).on(qOrderContract.order.id.eq(qOrder.id))
                .leftJoin(qOrderProduct).on(qOrder.id.eq(qOrderProduct.order.id))
                .where(qOrderContract.contractId.eq(feignVO.getContractId()));

        if(StringUtils.hasLength(feignVO.getOrderNo())) {
            query.where(qOrder.orderNo.like("%" + feignVO.getOrderNo().trim() + "%"));
        }

        if(StringUtils.hasLength(feignVO.getDigest())) {
            query.where(qOrder.digest.like("%" + feignVO.getDigest().trim() + "%"));
        }

        if(NumberUtil.notNullAndPositive(feignVO.getStartTime())) {
            query.where(qOrder.createTime.after(DateUtil.convertToLocalDateTime(feignVO.getStartTime())));
        }

        if(NumberUtil.notNullAndPositive(feignVO.getEndTime())) {
            query.where(qOrder.createTime.before(DateUtil.convertToLocalDateTime(feignVO.getEndTime())));
        }

        List<OrderAfterSaleOrderContractFeignVO> result = query.transform(GroupBy.groupBy(qOrderProduct.tax, qOrderProduct.taxRate).as(GroupBy.list(Projections.constructor(OrderAfterSaleOrderContractFeignVO.class,
                qOrder.id,
                qOrder.orderNo,
                qOrder.digest,
                qOrder.orderType,
                qOrder.createTime,
                qOrderProduct.refPrice,
                qOrderProduct.quantity,
                qOrderProduct.tax,
                qOrderProduct.taxRate,
                qOrder.outerStatus
        )))).values().stream().flatMap(Collection::stream).collect(Collectors.toList());

        result.forEach(r -> r.setOuterStatusName(OrderOuterStatusEnum.getNameByCode(r.getOuterStatus())));

        return Wrapper.success(result);
    }

    /**
     * 售后能力 - 查询已经确认支付结果的支付记录列表
     *
     * @param feignVO 接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<List<OrderAfterSalePaymentFeignDetailVO>> findAfterSaleOrderPayments(OrderIdsFeignVO feignVO) {
        QOrderPaymentDO qOrderPayment = QOrderPaymentDO.orderPaymentDO;
        QOrderDO qOrder = QOrderDO.orderDO;

        JPAQuery<OrderAfterSalePaymentFeignDetailVO> query = jpaQueryFactory.select(Projections.constructor(OrderAfterSalePaymentFeignDetailVO.class, qOrderPayment.order.id, qOrderPayment.order.orderNo, qOrderPayment.id, qOrderPayment.payTime, qOrderPayment.batchNo, qOrderPayment.payNode, qOrderPayment.payRate, qOrderPayment.payAmount, qOrderPayment.fundMode, qOrderPayment.payType, qOrderPayment.payChannel, qOrderPayment.tradeNo, qOrderPayment.settlementStatus, qOrder.outerStatus.eq(OrderOuterStatusEnum.TO_CONFIRM_PAYMENT.getCode()), qOrderPayment.outerStatus.eq(OrderOuterStatusEnum.ACCOMPLISHED.getCode())))
                .from(qOrderPayment)
                .leftJoin(qOrder).on(qOrderPayment.order.id.eq(qOrder.id))
                .where(qOrderPayment.payAmount.gt(BigDecimal.ZERO));

        if(!CollectionUtils.isEmpty(feignVO.getOrderIds())) {
            query.where(qOrderPayment.order.id.in(feignVO.getOrderIds()));
        } else {
            query.where(qOrderPayment.order.orderNo.in(feignVO.getOrderNos()));
        }

        return Wrapper.success(query.fetch());
    }

    /**
     * 物流能力 - 确认物流单后，更新订单的物流单号
     *
     * @param feignVO 接口参数
     * @return 更新结果
     */
    @Transactional(rollbackFor = BusinessException.class)
    @Override
    public Wrapper<Void> updateOrderLogisticsNo(OrderUpdateLogisticsNoFeignVO feignVO) {
        QOrderDO qOrder = QOrderDO.orderDO;
        jpaQueryFactory.update(qOrder).where(qOrder.id.eq(feignVO.getOrderId())).set(qOrder.logisticsNo, feignVO.getLogisticsNo()).execute();
        return Wrapper.success();
    }

    /**
     * 加工能力 - 更新订单商品加工数量
     *
     * @param feigns 接口参数
     * @return 更新结果
     */
    @Override
    public Wrapper<Void> updateOrderProductEnhanceCount(List<OrderUpdateEnhanceFeignVO> feigns) {
        if(CollectionUtils.isEmpty(feigns)) {
            return Wrapper.success();
        }

        List<OrderProductDO> orderProducts = orderProductRepository.findAllById(feigns.stream().map(OrderUpdateEnhanceFeignVO::getOrderProductId).collect(Collectors.toList()));
        orderProducts.forEach(orderProduct -> feigns.stream().filter(feignProduct -> feignProduct.getOrderProductId().equals(orderProduct.getId())).findFirst().ifPresent(feignProduct -> orderProduct.setEnhanceCount(orderProduct.getEnhanceCount().add(feignProduct.getEnhanceCount()))));
        orderProductRepository.saveAll(orderProducts);
        return Wrapper.success();
    }

    /**
     * 结算服务 - 查询订单发票信息
     *
     * @param feignVO 接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<OrderSettleAccountInvoiceFeignDetailVO> findSettleAccountInvoiceDetail(OrderNoFeignVO feignVO) {
        QOrderInvoiceDO qOrderInvoice = QOrderInvoiceDO.orderInvoiceDO;
        QOrderDO qOrder = QOrderDO.orderDO;
        return Wrapper.success(jpaQueryFactory.select(Projections.constructor(OrderSettleAccountInvoiceFeignDetailVO.class, qOrderInvoice.id, qOrder.id, qOrder.orderNo, qOrderInvoice.invoiceId, qOrderInvoice.invoiceKind, qOrderInvoice.invoiceType, qOrderInvoice.title, qOrderInvoice.taxNo, qOrderInvoice.bank, qOrderInvoice.account, qOrderInvoice.address, qOrderInvoice.phone, qOrderInvoice.defaultInvoice))
                .from(qOrderInvoice)
                .leftJoin(qOrder).on(qOrderInvoice.order.id.eq(qOrder.id))
                .where(qOrder.orderNo.eq(feignVO.getOrderNo())).fetchFirst());
    }

    /**
     * 会员服务 - 订单评论完成后，更改订单评论状态
     *
     * @param feignVO 接口参数
     * @return 修改结果
     */
    @Transactional(rollbackFor = BusinessException.class)
    @Override
    public Wrapper<Void> updateOrderComment(OrderCommentFeignVO feignVO) {
        QOrderDO qOrder = QOrderDO.orderDO;
        if(Objects.nonNull(feignVO.getBuyerCommentComplete()) && feignVO.getBuyerCommentComplete()) {
            jpaQueryFactory.update(qOrder).where(qOrder.id.eq(feignVO.getOrderId())).set(qOrder.buyerCommented, true).execute();
        }

        if(Objects.nonNull(feignVO.getVendorCommentComplete()) && feignVO.getVendorCommentComplete()) {
            jpaQueryFactory.update(qOrder).where(qOrder.id.eq(feignVO.getOrderId())).set(qOrder.vendorCommented, true).execute();
        }

        return Wrapper.success();
    }

    /**
     * 支付服务 - 订单服务回调
     *
     * @param callbackFeignVO 接口参数
     * @return 操作结果
     */
    @Override
    public Wrapper<Void> orderPayCallback(OrderPayCallbackFeignVO callbackFeignVO) {
        logger.info("feign接收到回调：" + OrderStringUtil.serializeObject(callbackFeignVO));
        return buyerOrderService.orderPayCallback(callbackFeignVO.getTradeNo(), callbackFeignVO.getAttach(), callbackFeignVO.getPaySuccess());
    }

    /**
     * 售后服务 - 订单会员信息校验
     * @param checkVO 请求参数
     * @return 操作结果
     */
    @Override
    public Wrapper<Boolean> checkAfterSaleOrderMember(CheckOrderMemberAfterSaleVO checkVO) {
        if (CollUtil.isEmpty(checkVO.getOrderIds())) {
            return Wrapper.success(false);
        }
        int count = orderRepository.countByIdInAndBuyerMemberIdAndBuyerRoleIdAndVendorMemberIdAndVendorRoleId(checkVO.getOrderIds(), checkVO.getBuyerMemberId(), checkVO.getBuyerRoleId(), checkVO.getVendorMemberId(), checkVO.getVendorRoleId());
        if (count == checkVO.getOrderIds().size()) {
            return Wrapper.success(true);
        }
        return Wrapper.success(false);
    }

    @Override
    public Wrapper<List<PlatformSettlementTypeVO>> findSettlementTypeByStatusEqualEnable() {
        return platformSettlementTypeService.findSettlementTypeByEnable();
    }

    @Override
    public Wrapper<List<MemberSettleChannelVO>> findSettlementChannel(MemberSettleChannelQueryVO queryVO) {
        QMemberPaymentParameterDO qPlatformPaymentParameterDO = QMemberPaymentParameterDO.memberPaymentParameterDO;
        List<MemberSettleChannelVO> data = jpaQueryFactory.select(Projections.bean(MemberSettleChannelVO.class,
                        qPlatformPaymentParameterDO.payChannel,
                        qPlatformPaymentParameterDO.payChannelName))
                .from(qPlatformPaymentParameterDO)
                .where(qPlatformPaymentParameterDO.payType.eq(queryVO.getPayType()),
                        qPlatformPaymentParameterDO.memberId.eq(queryVO.getMemberId()),
                        qPlatformPaymentParameterDO.roleId.eq(queryVO.getRoleId())).fetch();
        return Wrapper.success(data);
    }

    /**
     * 查询平台规则配置
     *
     * @param feignVO 查询条件
     * @return 查询结果
     */
    @Override
    public Wrapper<List<OrderRuleDetailVO>> findOrderRules(OrderRuleDetailFeignVO feignVO) {
        QBaseOrderRuleDO qBaseOrderRule = QBaseOrderRuleDO.baseOrderRuleDO;
        JPAQuery<OrderRuleDetailVO> query = jpaQueryFactory.select(Projections.constructor(OrderRuleDetailVO.class, qBaseOrderRule.ruleType, qBaseOrderRule.ruleName, qBaseOrderRule.methodCode, qBaseOrderRule.methodName, qBaseOrderRule.status))
                .from(qBaseOrderRule);

        if(NumberUtil.notNullOrZero(feignVO.getRuleType())) {
            query.where(qBaseOrderRule.ruleType.eq(feignVO.getRuleType()));
        }

        if(NumberUtil.notNullOrZero(feignVO.getMethodCode())) {
            query.where(qBaseOrderRule.methodCode.eq(feignVO.getMethodCode()));
        }

        if(NumberUtil.notNullOrZero(feignVO.getStatus())) {
            query.where(qBaseOrderRule.status.eq(feignVO.getStatus()));
        }

        return Wrapper.success(query.fetch());
    }

    /**
     * 营销服务 - 查询订单商品信息
     *
     * @param feignVO 查询条件
     * @return 查询结果
     */
    @Override
    public Wrapper<List<OrderMarketingDetailVO>> findOrderMarketingProducts(OrderMarketingFeignVO feignVO) {
        QOrderDO qOrder = QOrderDO.orderDO;
        QOrderProductDO qOrderProduct = QOrderProductDO.orderProductDO;

        List<OrderMarketingDetailVO> result = jpaQueryFactory.select(Projections.constructor(OrderMarketingDetailVO.class, qOrder.id, qOrderProduct.skuId, qOrder.outerStatus, qOrderProduct.tax, qOrderProduct.taxRate, qOrderProduct.price, qOrderProduct.refPrice, qOrderProduct.quantity))
                .from(qOrder).leftJoin(qOrderProduct).on(qOrder.id.eq(qOrderProduct.order.id))
                .where(qOrder.id.in(feignVO.getOrderIds()).and(qOrderProduct.skuId.in(feignVO.getSkuIds())))
                .fetch();

        result.forEach(r -> r.setOuterStatusName(OrderOuterStatusEnum.getNameByCode(r.getOuterStatus())));

        return Wrapper.success(result);
    }

    /**
     * 会员服务 - 查询订单供应会员会员Logo、或店铺Logo、或自营商城Logo
     * @param feignVO 接口参数
     * @return 修改结果
     */
    @Override
    public Wrapper<List<OrderVendorLogoFeignVO>> findOrderVendorLogo(OrderFeignIdsVO feignVO) {
        QOrderDO qOrder = QOrderDO.orderDO;
        List<OrderVendorLogoFeignVO> orderList = jpaQueryFactory.select(Projections.constructor(OrderVendorLogoFeignVO.class, qOrder.id, qOrder.vendorLogo)).from(qOrder).where(qOrder.id.in(feignVO.getOrderIds())).fetch();
        return Wrapper.success(orderList);
    }

    /**
     * 结算能力 - 新增请款单-查询请款类型和付款方过滤采购订单数据
     * @param pageVO 接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<PageData<OrderBuyerSettleQueryVO>> pageSettleBuyerOrders(OrderBuyerSettlePageVO pageVO) {
        QOrderDO qOrder = QOrderDO.orderDO;
        QOrderProductDO qOrderProduct = QOrderProductDO.orderProductDO;
        QOrderContractDO qOrderContractDO = QOrderContractDO.orderContractDO;

        JPAQuery<OrderBuyerSettleQueryVO> query = jpaQueryFactory.from(qOrder)
                .select(Projections.constructor(OrderBuyerSettleQueryVO.class, qOrderContractDO.contractId.coalesce(0L), qOrder.id, qOrder.orderNo, qOrder.digest, qOrder.createTime, qOrder.buyerInnerStatus, qOrder.productAmount, qOrderProduct.tax, qOrderProduct.taxRate, qOrderProduct.amount.sum()))
                .leftJoin(qOrderProduct).on(qOrder.id.eq(qOrderProduct.order.id))
                .leftJoin(qOrderContractDO).on(qOrder.contract.id.eq(qOrderContractDO.id))
                .where(qOrder.buyerMemberId.eq(pageVO.getBuyerMemberId()).and(qOrder.buyerRoleId.eq(pageVO.getBuyerRoleId())).and(qOrder.orderType.eq(pageVO.getOrderType())).and(qOrder.buyerInnerStatus.ne(BuyerInnerStatusEnum.CANCELLED.getCode())))
                .groupBy(qOrderContractDO.contractId,qOrder.id, qOrderProduct.tax, qOrderProduct.taxRate);

        //订单号
        if (StrUtil.isNotEmpty(pageVO.getOrderNo())) {
            query.where(qOrder.orderNo.like("%" + pageVO.getOrderNo().trim() + "%"));
        }

        //订单摘要
        if (StrUtil.isNotEmpty(pageVO.getDigest())) {
            query.where(qOrder.digest.like("%" + pageVO.getDigest().trim() + "%"));
        }

        //订单起始时间
        if (StrUtil.isNotEmpty(pageVO.getStartDate())) {
            query.where(qOrder.createTime.after(LocalDateTime.parse(pageVO.getStartDate().concat(" 00:00:00"), OrderServiceContants.DEFAULT_TIME_FORMATTER)));
        }

        //订单起始时间
        if (StrUtil.isNotEmpty(pageVO.getEndDate())) {
            query.where(qOrder.createTime.before(LocalDateTime.parse(pageVO.getEndDate().concat(" 23:59:59"), OrderServiceContants.DEFAULT_TIME_FORMATTER)));
        }
        long totalCount = query.fetch().size();
        query.orderBy(qOrder.id.desc());
        query.limit(pageVO.getPageSize()).offset(pageVO.getCurrentOffset());
        List<OrderBuyerSettleQueryVO> result = query.fetch();
        result.forEach(v -> v.setStatusName(BuyerInnerStatusEnum.getNameByCode(v.getStatus())));

        return Wrapper.success(new PageData<>(totalCount, result));
    }

    /**
     * 结算服务 - 付款完成后修改订单收发货记录状态为已结算
     * @param feignVO 接口参数
     */
    @Async
    @Override
    @Transactional(rollbackFor = BusinessException.class)
    public void updateOrderDeliveries(OrderUpdateDeliveriesFeignVO feignVO) {
        QOrderDeliveryDO qOrderDelivery = QOrderDeliveryDO.orderDeliveryDO;

        jpaQueryFactory.update(qOrderDelivery).where(qOrderDelivery.order.id.eq(feignVO.getOrderId()).and(qOrderDelivery.batchNo.eq(feignVO.getBatchNo()))).set(qOrderDelivery.buyerInnerStatus, BuyerInnerStatusEnum.HAVE_SETTLED.getCode()).execute();
    }

    /**
     * 结算服务 - 协同对账 - 对账单生成请款单采购订单数据
     * @param feignVO 接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<List<OrderBuyerSettleReconciliationFeignVO>> settleReconciliationBuyerOrders(OrderFeignIdsVO feignVO) {
        QOrderDO qOrder = QOrderDO.orderDO;
        QOrderProductDO qOrderProduct = QOrderProductDO.orderProductDO;

        JPAQuery<OrderBuyerSettleReconciliationFeignVO> query = jpaQueryFactory.from(qOrder)
                .select(Projections.constructor(OrderBuyerSettleReconciliationFeignVO.class, qOrder.id, qOrderProduct.tax, qOrderProduct.taxRate, qOrderProduct.amount.sum()))
                .leftJoin(qOrderProduct).on(qOrder.id.eq(qOrderProduct.order.id))
                .where(qOrder.id.in(feignVO.getOrderIds()))
                .groupBy(qOrder.id, qOrderProduct.tax, qOrderProduct.taxRate);

        return Wrapper.success(query.fetch());
    }

    /**
     * “售后服务” - 查询订单商品使用“平台优惠券”后的优惠抵扣金额
     *
     * @param feignVO 接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<List<OrderProductCouponFeignVO>> findOrderProductCouponAmounts(OrderFeignIdsVO feignVO) {
        QOrderDO qOrder = QOrderDO.orderDO;
        QOrderCouponDO qOrderCoupon = QOrderCouponDO.orderCouponDO;
        QOrderProductDO qOrderProduct = QOrderProductDO.orderProductDO;

        //查询订单是否有“平台优惠券”，每个订单最多只能使用一个“平台优惠券”
        return Wrapper.success(jpaQueryFactory.select(Projections.constructor(OrderProductCouponFeignVO.class, qOrderProduct.id, qOrderProduct.skuId, qOrderCoupon.couponId, qOrderProduct.platformCouponAmount))
                .from(qOrder)
                .leftJoin(qOrderCoupon).on(qOrder.id.eq(qOrderCoupon.order.id))
                .leftJoin(qOrderProduct).on(qOrder.id.eq(qOrderProduct.order.id))
                .where(qOrder.id.in(feignVO.getOrderIds()).and(qOrderCoupon.belongType.eq(BelongTypeEnum.PLATFORM.getCode())))
                .fetch());
    }

    @Override
    public Wrapper<List<OrderFreeExpressConfigVO>> getOrderFreeExpressConfigList(OrderFreeExpressFeignVO feignVO) {
        //构造多字段查询条件
        List<MemberAndRoleIdDTO> memberAndRoleIdDTOS = feignVO.getItemList().stream().map(o -> {
            return new MemberAndRoleIdDTO(o.getMemberId(), o.getRoleId());
        }).collect(Collectors.toList());
        return Wrapper.success(orderParamConfigService.getOrderFreeExpressConfigList(memberAndRoleIdDTOS));
    }


    public Wrapper<List<OrderScoreConfigVO>> getOrderScoreConfigList(OrderScoreFeignVO feignVO) {
        //构造多字段查询条件
        List<MemberAndRoleIdDTO> memberAndRoleIdDTOS = feignVO.getItemList().stream().map(o -> new MemberAndRoleIdDTO(o.getMemberId(), o.getRoleId())).collect(Collectors.toList());
        return Wrapper.success(orderParamConfigService.getOrderScoreConfigList(memberAndRoleIdDTOS));
    }

    /**
     * 根据物料信息查询订单(商品能力- 物料价格库)
     * @author lxc
     * @date 2022/4/2
     **/
    @Override
    public Wrapper<OrderPriceQueryVO> goodsPriceByGoods(OrderPriceQueryRequest request) {
        String code = request.getCode();
        Long memberId = request.getMemberId();
        Long memberRoleId = request.getMemberRoleId();
        QOrderProductDO qOrderProductDO = QOrderProductDO.orderProductDO;
        QOrderDO qOrderDO = QOrderDO.orderDO;
        BooleanBuilder predicates = new BooleanBuilder();
        predicates.and(qOrderDO.buyerMemberId.eq(memberId));
        predicates.and(qOrderDO.buyerRoleId.eq(memberRoleId));
        //订单类型为 采购询价合同、采购竞价合同、采购招标合同、请购单采购
        predicates.and(qOrderDO.orderType.in(OrderTypeEnum.QUERY_PRICE_CONTRACT.getCode(), OrderTypeEnum.PRICE_COMPETITION_CONTRACT_PURCHASE.getCode(), OrderTypeEnum.PURCHASE_CONTRACT_BIDDING.getCode(), OrderTypeEnum.REQUISITION_TO_PURCHASE.getCode()));
        predicates.and(qOrderProductDO.productNo.eq(code));

        JPAQuery<OrderPriceQueryVO> query = jpaQueryFactory.select(
                Projections.bean(OrderPriceQueryVO.class,
                        qOrderProductDO.productNo.as("code"),
                        qOrderProductDO.price.as("totalAmount"),
                        qOrderDO.orderNo.as("contractNo"),
                        qOrderDO.createTime.as("startTime"),
                        qOrderDO.createTime.as("endTime"),
                        qOrderDO.vendorMemberName.as("partyBName"),
                        qOrderDO.vendorMemberId.as("partyBMemberId"),
                        qOrderDO.vendorRoleId.as("partyBRoleId")))
                .from(qOrderDO)
                .innerJoin(qOrderProductDO)
                .on(qOrderDO.id.eq(qOrderProductDO.order.id))
                .where(predicates);
        List<OrderPriceQueryVO> queryVOS = query.fetch();
        if (CollectionUtils.isEmpty(queryVOS)){
            return Wrapper.success(null);
        }
        //筛选最新的合同信息
        OrderPriceQueryVO response = queryVOS.stream().max(Comparator.comparing(OrderPriceQueryVO::getStartTime)).orElse(null);
        return Wrapper.success(response);
    }
}
